﻿namespace SipSharp.Messages.Headers
{
    /// <summary>
    /// Authorization header
    /// </summary>
    /// <remarks>
    /// Second part in authentication process. The UAS have sent a
    /// <see cref="Authenticate"/> header and the UAC responds with this one.
    /// </remarks>
    /// <example>
    /// Authorization: Digest username="bob",
    ///                 realm="biloxi.com",
    ///                 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
    ///                 uri="sip:bob@biloxi.com",
    ///                 qop=auth,
    ///                 nc=00000001,
    ///                 cnonce="0a4f113b",
    ///                 response="6629fae49393a05397450978507c4ef1",
    ///                 opaque="5ccc069c403ebaf9f0171e9517f40e41"
    /// </example>
    public class Authorization : IHeader
    {
        public const string LNAME = "authorization";
        public const string NAME = "Authorization";
        public const string PROXY_LNAME = "proxy-authorization";
        public const string PROXY_NAME = "Proxy-Authorization";

        /// <summary>
        /// Initializes a new instance of the <see cref="Authorization"/> class.
        /// </summary>
        /// <param name="name">Header name.</param>
        public Authorization(string name)
        {
            Name = name;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Authorization"/> class.
        /// </summary>
        public Authorization()
        {
            Name = NAME;
        }

        /// <summary>
        /// Gets or sets a string indicating a pair of algorithms used to produce the digest and a checksum.
        /// </summary>
        /// <remarks>
        /// If this is not present it is assumed to be "MD5". If the algorithm is not understood, the challenge should be ignored (and a different one used, if there is more than one).
        /// </remarks>
        public string Algortihm { get; set; }

        /// <summary>
        /// Gets or sets client generated nonce.
        /// </summary>
        public string ClientNonce { get; set; }

        /// <summary>
        /// Gets or sets a server-specified data string which should be uniquely generated each time a 401 response is made.
        /// </summary>
        /// <remarks>
        /// It is recommended that this string be base64 or hexadecimal data. Specifically, since the string is passed in the header lines as a quoted string, the double-quote character is not allowed.
        /// </remarks>
        public string Nonce { get; set; }

        /// <summary>
        /// Gets or sets nonce counter
        /// </summary>
        public int NonceCounter { get; set; }

        /// <summary>
        /// Gets or sets a string of data, specified by the server, which should be returned by the client unchanged in the Authorization header of subsequent requests with URIs in the same protection space.
        /// </summary>
        public string Opaque { get; set; }

        /// <summary>
        /// Gets or sets quality of protection.
        /// </summary>
        /// <remarks>
        /// If present, its value MUST be one of the alternatives the server indicated it supports in the WWW-Authenticate header
        /// </remarks>
        public string Qop { get; set; }

        /// <summary>
        /// Gets or sets domain used to calc response.
        /// </summary>
        public string Realm { get; set; }

        /// <summary>
        /// Gets or sets reponse generated by the server.
        /// </summary>
        public string Response { get; set; }

        /// <summary>
        /// Gets or sets URI to authenticate
        /// </summary>
        public SipUri Uri { get; set; }

        /// <summary>
        /// Gets or sets user being authenticated.
        /// </summary>
        public string UserName { get; set; }

        #region IHeader Members

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public object Clone()
        {
            return MemberwiseClone();
        }


        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.
        ///                 </param>
        public bool Equals(IHeader other)
        {
            var obj = other as Authorization;
            if (obj == null)
                return false;

            return Uri == obj.Uri && Opaque == obj.Opaque;
        }

        /// <summary>
        /// Gets header name
        /// </summary>
        public string Name { get; private set; }

        #endregion
    }
}